package org.geekbang.thinking.in.spring.dependency.lookup;

import org.geekbang.thinking.in.spring.ioc.overview.domain.User;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import java.util.Map;

/**
 * 类型安全依赖查找示例
 *
 */
public class TypeSafetyDependencyLookup {

    public static void main(String[] args) {
        // 创建 BeanFactory 容器
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        // 将当前类 ObjectProviderDemo 作为配置类
        applicationContext.register(TypeSafetyDependencyLookup.class);
        // 启动应用上下文
        applicationContext.refresh();

        // 演示 BeanFactory#getBean 方法的安全性（不安全）
        // displayBeanFactoryGetBean(applicationContext);
        // 演示 ObjectFactory#getObject 方法的安全性（不安全）
        // displayObjectFactoryGetObject(applicationContext);
        // 演示 ObjectProvider#getIfAvailable 方法的安全性（安全）
        // displayObjectProviderGetIfAvailable(applicationContext);

        // 演示 ListableBeanFactory#getBeansOfType 方法的安全性（安全）
        // displayListableBeanFactoryGetBeansOfType(applicationContext);
        // 演示 ObjectProvider#stream 方法的安全性（安全）
        displayObjectProviderStream(applicationContext);

        // 关闭应用上下文
        applicationContext.close();
    }

    private static void displayObjectProviderStream(AnnotationConfigApplicationContext applicationContext) {
        ConfigurableListableBeanFactory beanFactory = applicationContext.getBeanFactory();
        ObjectProvider<User> objectProvider = beanFactory.getBeanProvider(User.class);
        try {
            objectProvider.stream().forEach(System.out::println);
        } catch (BeansException e) {
            e.printStackTrace();
        }
    }

    private static void displayListableBeanFactoryGetBeansOfType(AnnotationConfigApplicationContext applicationContext) {
        ConfigurableListableBeanFactory beanFactory = applicationContext.getBeanFactory();
        try {
            System.out.println(beanFactory.getBeansOfType(User.class));
        } catch (BeansException e) {
            e.printStackTrace();
        }
    }

    private static void displayObjectProviderGetIfAvailable(AnnotationConfigApplicationContext applicationContext) {
        ConfigurableListableBeanFactory beanFactory = applicationContext.getBeanFactory();
        ObjectProvider<User> objectProvider = beanFactory.getBeanProvider(User.class);
        try {
            User user = objectProvider.getIfAvailable();
            System.out.println(user);
        } catch (BeansException e) {
            e.printStackTrace();
        }

    }

    private static void displayObjectFactoryGetObject(BeanFactory beanFactory) {
        ObjectProvider<User> objectProvider = beanFactory.getBeanProvider(User.class);
        try {
            objectProvider.getObject();
        } catch (BeansException e) {
            e.printStackTrace();
        }
    }

    private static void displayBeanFactoryGetBean(BeanFactory beanFactory) {
        try {
            beanFactory.getBean(User.class);
        } catch (BeansException e) {
            e.printStackTrace();
        }
    }
}
